package test;

import java.awt.Color;
import java.awt.Component;

import javax.swing.AbstractCellEditor;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;

class TableDemo13 extends JFrame
{
  TableDemo13 (String title)
  {
   // Pass the title to the JFrame superclass so that it appears in
   // the title bar.

   super (title);

   // Tell the program to exit when the user either selects Close
   // from the System menu or presses an appropriate X button on the 
   // title bar.

   setDefaultCloseOperation (EXIT_ON_CLOSE);

   // Create a my table model consisting of 4 rows by 3 columns.

   MyTableModel mtm = new MyTableModel (4, 3);

   // Assign column identifiers (headers) to the columns.

   String [] columnTitles =
   {
     "Name",
     "Address",
     "Favorite Color",
   };

   mtm.setColumnIdentifiers (columnTitles);

   // Populate all cells in the my table model.

   String [] names =
   {
     "John Doe",
     "Jane Smith",
     "Jack Jones",
     "Paul Finch"
   };

   String [] addresses =
   {
     "200 Fox Street",
     "Apt. 555",
     "Box 9000",
     "1888 Apple Avenue"
   };

   Color [] favoriteColors =
   {
     Color.red,
     Color.blue,
     Color.green,
     Color.red
   };

   int nrows = mtm.getRowCount ();

   for (int i = 0; i < nrows; i++)
   {
      mtm.setValueAt (names [i], i, 0);
      mtm.setValueAt (addresses [i], i, 1);
      mtm.setValueAt (favoriteColors [i], i, 2);
   }

   // Create a table using the previously created default table
   // model.

   JTable jt = new JTable (mtm);

   // Establish a color renderer for the third column.

   jt.getColumnModel ().getColumn (2).
              setCellRenderer (new ColorRenderer());

   // Establish a color editor for the third column.

   jt.getColumnModel ().getColumn (2).
              setCellEditor (new ColorEditor ());

   // Place the table in a JScrollPane object (to allow the table to
   // be vertically scrolled and display scrollbars, as necessary).

   JScrollPane jsp = new JScrollPane (jt);

   // Add the JScrollPane object to the frame window's content pane.
   // That allows the table to be displayed within a displayed
   // scroll pane.

   getContentPane ().add (jsp);

   // Establish the overall size of the frame window to 400
   // horizontal pixels by 110 vertical pixels.

   setSize (400, 110);

   // Display the frame window and all contained
   // components/containers.

   setVisible (true);
  }

  public static void main (String [] args)
  {
   // Create a TableDemo13 object, which creates the GUI.

   new TableDemo13 ("Table Demo #13");
  }
}

class ColorEditor extends AbstractCellEditor implements TableCellEditor
{
  private JLabel l = new JLabel ("");

  public Object getCellEditorValue ()
  {
   // Return the label's background color so that it can be stored
   // in the table component's model.

   return l.getBackground ();
  }

  public Component getTableCellEditorComponent (JTable table,
                         Object value,
                         boolean isSelected,
                         int row,
                         int column)
  {
   if (value instanceof Color)
   {
     // Display a JColorChooser dialog box that allows the user to
     // choose a color from a visual color picker.

     Color c = JColorChooser.showDialog (null, "Choose color",
                       (Color) value);

     // If user didn't Cancel the Color Chooser, set the label's
     // background to the chosen color, as expressed via a Color
     // object. Otherwise, assign the Color object, as expressed
     // by value, to the label's background. If that is not done,
     // a future return l.getBackground (); in 
     // getCellEditorValue() will return the most recently set 
     // background color, which will then be assigned to the table
     // component's model. That color will most likely not be the
     // same as the color passed in value. As a result, a cell's 
     // original background color will disappear.

     if (c != null)
       l.setBackground (c);
     else
       l.setBackground ((Color) value);
   }

   // Return a reference to the component that does the editing.
   // Because a JLabel reference is being returned, there won't be
   // any editing. The reason editing isn't needed is that the color
   // chooser is being used to obtain the color.

   return l;
  }
}

class ColorRenderer extends DefaultTableCellRenderer
{
  public Component getTableCellRendererComponent (JTable table,
                          Object value,
                          boolean isSelected,
                          boolean isFocus,
                          int row,
                          int column)
  {
   if (value instanceof Color)
     setBackground ((Color) value);

   // Prevent value.toString ()'s returned String from being
   // rendered.

   value = ""; 

   // Allow the superclass to complete configuring the renderer.

   return super.getTableCellRendererComponent (table, value,
                         isSelected, isFocus,
                         row, column);
  }
}

class MyTableModel extends DefaultTableModel
{
  MyTableModel (int rows, int cols)
  {
   super (rows, cols);
  }

  public Class getColumnClass (int columnIndex)
  {
   // If column is the Favorite color column, return Color.class so
   // that the Color renderer and editor will be used.

   if (columnIndex == 2)
     return Color.class;
   else
     return Object.class;
  }
}